package com.protocol;

import com.config.Config;
import com.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author linyu.dai
 * @project rpc
 * @description 消息通信协议
 * @creat 2022/11/27 11:58:41
 */
@Slf4j
@ChannelHandler.Sharable
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, Message> {

    private static final int SERIALIZER_TYPE = Serializer.Algorithm.valueOf(Config.get("rpc.serializer.type")).ordinal();

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> out) throws Exception {
        //获取一个ByteBuf
        ByteBuf buf = ctx.alloc().buffer();
        //魔数 4个字节
        buf.writeBytes(new byte[]{'a', 'b', 'c', 'd'});
        //版本号 1个字节
        buf.writeByte(1);
        //序列化方式 读取配置文件 1个字节
        buf.writeByte(SERIALIZER_TYPE);
        //设置消息类型 1个字节
        buf.writeByte(msg.getMessageType());
        //设置序列化id 4个字节
        buf.writeInt(msg.getSequenceId());
        //对其填充 1个字节 满足12个字节
        buf.writeByte(0xff);

        byte[] bytes = Serializer.Algorithm.values()[SERIALIZER_TYPE].serializer(msg);
        //内容长度 4个字节
        buf.writeInt(bytes.length);
        //全部内容
        buf.writeBytes(bytes);

//        log.info("send message {}, messageType: {}", msg, msg.getMessageType());
        ctx.channel().writeAndFlush(buf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        //魔数
        msg.readBytes(4);
        //版本号
        msg.readByte();
        //反序列化方式
        byte serializerType = msg.readByte();
        //消息类型
        byte messageType = msg.readByte();
        //设置序列化id 4个字节
        msg.readInt();
        //对其填充
        msg.readByte();

        //内容长度
        int length = msg.readInt();
        byte[] bytes = new byte[length];
        msg.readBytes(bytes, 0, length);

        //读取内容
        Message message = Serializer.Algorithm.values()[serializerType].deserialize(Message.getMessageClass(messageType), bytes);

//        log.info("receive message {}, messageType:{}", message, messageType);
        out.add(message);
    }
}
